package com 
{
	import com.greensock.motionPaths.Direction;
	import data.*;
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.utils.Dictionary;
	
	/**
	 * ...
	 * @author Jason Won
	 */
	public class GCShip
	{
		// The unique id for this ship, used for the database
		private var _uid:uint;
		
		// The type of this ship
		private var _type:uint;
		
		/*
		 * Related to the statistics of this ship.
		 */
		public var _stats:Vector.<uint>;
		
		/*
		 * Keep track of upgrades.
		 * Key=slotId
		 * Value=ItemId of upgrade
		 * 
		 * (Note: an upgrade will be formatted in this fashion
		 * ItemId of upgrade will lead us to a separate associative array that
		 * lists various abilities as keys and its affect as a value)
		 */
		private var _upgradeSlots:Dictionary;
		
		/*
		 * Visual appearance of this ship, keep a dictionary keyed by
		 * the slot id to a sprite containing the image of the upgrade.
		 */
		private var _upgradeVisuals:Dictionary;
		private var _shipImage:Sprite;
		private var _upgradesAttachedList:Vector.<uint>;
		
		public function GCShip(uid:uint, type:uint, upgrades:Dictionary) 
		{
			this._uid = uid;
			this._type = type;
			this._stats = GCShipData.getStatsFromId(type); // TODO: Deep copy?
			_upgradeSlots = upgrades;
			
			_upgradesAttachedList = new Vector.<uint>();
			_shipImage = new Sprite();
			_upgradeVisuals = new Dictionary();
			
			/*
			 * Fill out the ship visually at the start.
			 */
			var imageName:String = GCShipData.getImageFromId(getType());
			_shipImage.addChild(GCResources.getResource(imageName));
			
			// Add a sail
			_shipImage.addChild(GCResources.getResource("Sail 1"));
			for (var obj:Object in _upgradeSlots)
			{
				var slotId:uint = obj as uint;
				
				// Attach only if upgrade can appear on ship
				if (_upgradeSlots[slotId] != GCItemData.ITEM_NULL &&
					GCItemData.getUpgradePositionFromId(_upgradeSlots[slotId], type) != null)
					this.attachVisually(slotId, _upgradeSlots[slotId]);
			}
			
			for each (var upgrade:uint in upgrades) {
				var enhancements:Dictionary = GCItemData.getUpgradeEnhancementsFromId(upgrade);
				for (var enhancement:String in enhancements) {
					_stats[enhancement] += enhancements[enhancement];
				}
			}
		}
		
		/**
		 * Add an upgrade to the ship
		 * 
		 * @param	position
		 * 			The slot id that the upgrade should take
		 * @param	upgradeId
		 * 			The id of the item that was placed on the ship
		 */
		public function addUpgrade(position:uint, upgradeId:uint):void
		{
			changeBasedOnUpgrade(upgradeId);
			_upgradeSlots[position] = upgradeId;
		}
		
		/**
		 * Remove an upgrade from the ship
		 * 
		 * @param	position
		 */
		public function removeUpgrade(position:uint):void
		{
			trace("GCShip-- Removing upgrade");
			changeBasedOnUpgrade(_upgradeSlots[position], true);
			_upgradeSlots[position] = GCItemData.ITEM_NULL;
		}
		
		// Get Functions
		public function getType():uint
		{
			return _type;
		}
		
		public function get shipId():uint
		{
			return _uid;
		}
		
		public function get stats():Vector.<uint>
		{
			return _stats;
		}
		
		/**
		 * Get back a mapping of slots to the id of the item that
		 * occupies that slot.
		 */
		public function get upgradeSlots():Dictionary
		{
			return _upgradeSlots;
		}
		
		public function get shipImage():Sprite
		{
			return _shipImage;
		}
		
		/** Set functions **/
		
		public function set shipId(newId:uint):void
		{
			_uid = newId;
		}
		
		private function changeBasedOnUpgrade(id:uint, isRemoving:Boolean = false):void
		{
			var modifier:int = (isRemoving) ? -1 : 1;
			
			var upgradeItem:uint = id;
			var enhancements:Dictionary = GCItemData.getUpgradeEnhancementsFromId(upgradeItem);
			
			/*
			 * Loop through all enhancements made by this upgrade and
			 * do the corect thing to have the upgrade take effect.
			 */
			for (var obj:Object in enhancements)
			{
				var enhancementType:uint = obj as uint;
				var enhancementAmount:uint = enhancements[enhancementType];
				_stats[enhancementType] += enhancementAmount * modifier;
			}
		}
		
		/**
		 * Attach the upgrade in the "Correct" looking place on the ship. A
		 * static
		 * 
		 * @param	itemId
		 */
		public function attachVisually(slotId:uint, itemId:uint):void
		{
			if (itemId == GCItemData.ITEM_NULL)
			{
				return;
			}
			
			/*
			 * Have to resize the images so they look good on the ship.
			 */
			var bitmap:Bitmap = GCResources.getResource(GCItemData.getNameFromId(itemId));
			var p:Point = GCItemData.getUpgradePositionFromId(itemId, _type);
			
			trace("GCShip-- Adding the upgrade to the ship");

			bitmap.x = p.x;
			bitmap.y = p.y;
			_upgradeVisuals[slotId] = bitmap;
			trace(bitmap.x + " " + bitmap.y);
			_shipImage.addChild(bitmap);
			
			_upgradesAttachedList.push(itemId);
		}
		
		public function removeVisually(slotId:uint):void
		{
			var bitmap:Bitmap = _upgradeVisuals[slotId];
			delete _upgradeVisuals[slotId];
			_shipImage.removeChild(bitmap);
			
			var removedUpgrade:uint = _upgradeSlots[slotId]
			_upgradesAttachedList.splice(_upgradesAttachedList.indexOf(removedUpgrade), 1);
		}
	}

}